package com.moonlight.demo;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Random;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.IoFuture;
import org.apache.mina.core.future.IoFutureListener;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.LineDelimiter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.moonlight.demo.custom.Consts;
import com.moonlight.demo.custom.CustomEncodingFactory;
import com.moonlight.demo.custom.CustomPackage;
import com.moonlight.mina.MinaHandler;

@Component
public class Client implements CommandLineRunner {
private final static Logger logger = LoggerFactory.getLogger(Client.class);
	
	// 端口号
	private final static int port = 3000;
	
	// 心跳最大连接时间
	private static final int idle_time = 20;
	
	// 心跳发送间隔
	private static final int heart_beat = 15;
	
	// 心跳发送包内容
	private static final String requestContent = "heart_request";
	
	// 心跳接受包内容
	private static final String responseContent = "heart_response";
	
	// 本地地址
	private static final String address = "localhost";

	@Override
	public void run(String... args) throws Exception {
		NioSocketConnector connector = new NioSocketConnector();
		connector.getSessionConfig().setReadBufferSize(1024);
		connector.getFilterChain().addLast("codec" , new ProtocolCodecFilter(new CustomEncodingFactory(Charset.forName("utf-8"))));
		KeepAliveMessageFactory factory = new KeepAliveMessageFactoryImpl();
		KeepAliveRequestTimeoutHandler timeoutHandler = new KeepAliveRequestTimeoutHandlerImpl();
		// 心跳检测过滤器
		// 客户端只关心读空闲
		KeepAliveFilter filter = new KeepAliveFilter(factory , IdleStatus.READER_IDLE , timeoutHandler);
		filter.setForwardEvent(true);
		// 客户端需要设置请求间隔时间
		filter.setRequestInterval(heart_beat);
		filter.setRequestTimeout(idle_time);
		connector.getFilterChain().addLast("alive" , filter);
		connector.setHandler(new MinaHandler());
		ConnectFuture future = connector.connect(new InetSocketAddress(address , port));
		future.addListener(new IoFutureListener<IoFuture>() {

			@Override
			public void operationComplete(IoFuture future) {
				// TODO Auto-generated method stub
				IoSession session = future.getSession();
				for(int i = 0 ; i < 10 ; i ++) {
					int flag = new Random().nextInt(2);
					byte type = 0x00;
					switch(flag) {
					case 0: 
						type = Consts.MESSAGE;
						break;
					case 1:
						type = Consts.HEART;
						break;
					}
					CustomPackage package1 = new CustomPackage(type, "hello,world");
					session.write(package1);
				}
			}
		});
	}
	
	private class KeepAliveMessageFactoryImpl implements KeepAliveMessageFactory {

		@Override
		public boolean isRequest(IoSession session, Object message) {
			// TODO Auto-generated method stub
			// 服务器不会请求客户端
			return false;
		}

		@Override
		public boolean isResponse(IoSession session, Object message) {
			CustomPackage package1 = (CustomPackage) message;
			if(package1.getContent().toString().equals(responseContent)) {
				logger.info("客户端接受服务端心跳响应");
				return true;
			} else {
				return false;
			}
		}

		@Override
		public Object getRequest(IoSession session) {
			// TODO Auto-generated method stub
			logger.info("客户端发送心跳");
			CustomPackage package1 = new CustomPackage(Consts.HEART , requestContent);
			return package1;
		}

		@Override
		public Object getResponse(IoSession session, Object request) {
			// TODO Auto-generated method stub
			// 客户端不会响应服务端
			return null;
		}
		
	}
}
